Hi
I am looking at previous code and I have come across a put function and one part about it is making me unsure.
put(mySkip, totalCol, (count1)"")
Is there any particular reason for the parenthesis around the count1?
Eric_Hillen - Thu Feb 03 11:26:37 EST 2011 |
|
Re: Put function help Mathias Mamsch - Thu Feb 03 12:19:13 EST 2011
Nope. DXL will ignore the parenthesis. Probably there was something more in the parenthesis, that has been deleted. Regards, Mathias
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
|
|
Re: Put function help llandale - Thu Feb 03 16:21:51 EST 2011 Mathias Mamsch - Thu Feb 03 12:19:13 EST 2011
Nope. DXL will ignore the parenthesis. Probably there was something more in the parenthesis, that has been deleted. Regards, Mathias
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
Right. You need those extra parenthesis around functions that have a single string parameter:
string Ret(string in_String)
{ print "Ret: >>" in_String "<<\n"
return(in_String)
}
string New1 = Ret("Hello") "xx\t" Ret("GoodBye") "yy\n"
print "New1: >>" New1 "<<\n"
string New2 = (Ret("Hello")) "xx\t" (Ret("GoodBye")) "yy\n"
print "New2: >>" New2 "<<\n"
Prints this:
Ret: >>GoodByeyy
<<
Ret: >>Helloxx GoodByeyy
<<
New1: >>Helloxx GoodByeyy
<<
Ret: >>Hello<<
Ret: >>GoodBye<<
New2: >>Helloxx GoodByeyy
<<
It appears that for the same reason's that one IBM dude in 1980 decided that the "date" field was just 2 characters, not 4, triggering the 2000 milienum sky-is-falling-all-systems-will-crash scare costing billions; someone at QSS decided to ignore normal parenthesis when the function had a single string parameter, causing concatenation of strings following, in this case New1 calls "Ret" with "Helloxx\t" instead of "Hello" as you'd expect. I often stay awake sleepless an night trying to figure out any reason whatsoever for doing that.
|
|
Re: Put function help Mathias Mamsch - Thu Feb 03 17:42:27 EST 2011 llandale - Thu Feb 03 16:21:51 EST 2011
Right. You need those extra parenthesis around functions that have a single string parameter:
string Ret(string in_String)
{ print "Ret: >>" in_String "<<\n"
return(in_String)
}
string New1 = Ret("Hello") "xx\t" Ret("GoodBye") "yy\n"
print "New1: >>" New1 "<<\n"
string New2 = (Ret("Hello")) "xx\t" (Ret("GoodBye")) "yy\n"
print "New2: >>" New2 "<<\n"
Prints this:
Ret: >>GoodByeyy
<<
Ret: >>Helloxx GoodByeyy
<<
New1: >>Helloxx GoodByeyy
<<
Ret: >>Hello<<
Ret: >>GoodBye<<
New2: >>Helloxx GoodByeyy
<<
It appears that for the same reason's that one IBM dude in 1980 decided that the "date" field was just 2 characters, not 4, triggering the 2000 milienum sky-is-falling-all-systems-will-crash scare costing billions; someone at QSS decided to ignore normal parenthesis when the function had a single string parameter, causing concatenation of strings following, in this case New1 calls "Ret" with "Helloxx\t" instead of "Hello" as you'd expect. I often stay awake sleepless an night trying to figure out any reason whatsoever for doing that.
In DXL you normally need no parenthesis when calling functions with one parameter. It is my strong belief that putting those extra parenthesis around the one parameter does not make the code any cleaner, safer or more maintainable. Why put a (...) when it is not necessary? Only because other languages do it? My suggestion is to always do it like this:
string Ret(string in_String) {
return " >>" in_String "<< "
}
string New1 = (Ret "A" "B") (Ret "C" "D") "\n"
print "New1: " New1 "\n"
string New2 = (Ret "A") "B" (Ret "C") "D\n"
print "New2: " New2 "\n"
Now the scope of the Ret calls is obvious and the code is very readable. Regards, Mathias
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
|
|
Re: Put function help Eric_Hillen - Fri Feb 04 09:21:48 EST 2011
I'm new to DXL, but I do have some background in C.
I appreciate the help.
|
|
Re: Put function help llandale - Fri Feb 04 14:04:56 EST 2011 Mathias Mamsch - Thu Feb 03 17:42:27 EST 2011
In DXL you normally need no parenthesis when calling functions with one parameter. It is my strong belief that putting those extra parenthesis around the one parameter does not make the code any cleaner, safer or more maintainable. Why put a (...) when it is not necessary? Only because other languages do it? My suggestion is to always do it like this:
string Ret(string in_String) {
return " >>" in_String "<< "
}
string New1 = (Ret "A" "B") (Ret "C" "D") "\n"
print "New1: " New1 "\n"
string New2 = (Ret "A") "B" (Ret "C") "D\n"
print "New2: " New2 "\n"
Now the scope of the Ret calls is obvious and the code is very readable. Regards, Mathias
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
The parens are essencial in this example since we are demonstrating how DXL, oddly, ignores the parens.
And it appears we disagree in principle putting the parens which certainly, in my mind, makes the code "clearer", especially to folks who are less familiar with the syntax of the function calls than is the author. And I know that this author becomes "less familiar" as time goes on.
And these extra un-needed parens certainly do not make it less understandable. This is something like inserting an extra blank line in the code to visually separate sections; not needed for the interpreter but is useful to the reader.
string Results = Ret "A". Now is "Ret" a constant, a function with no parameters, or a function with one parameter? What happens when there is a "Ret()" function and also a "Ret(In)" function?
string Results = Ret("A") is much easier to understand; now I look for a function with one parameter.
I routinely use empty parens for functions that have no parameters in order to make it clear that thing is a function doing something, not some variable only storing a value.
int iResults = 24+45*3/5-23+4*2
There are some folks who can see the order of precedence and apply it perfectly, but most of us cannot. We must use parens.
|
|
Re: Put function help Mathias Mamsch - Sat Feb 05 17:25:06 EST 2011 llandale - Fri Feb 04 14:04:56 EST 2011
The parens are essencial in this example since we are demonstrating how DXL, oddly, ignores the parens.
And it appears we disagree in principle putting the parens which certainly, in my mind, makes the code "clearer", especially to folks who are less familiar with the syntax of the function calls than is the author. And I know that this author becomes "less familiar" as time goes on.
And these extra un-needed parens certainly do not make it less understandable. This is something like inserting an extra blank line in the code to visually separate sections; not needed for the interpreter but is useful to the reader.
string Results = Ret "A". Now is "Ret" a constant, a function with no parameters, or a function with one parameter? What happens when there is a "Ret()" function and also a "Ret(In)" function?
string Results = Ret("A") is much easier to understand; now I look for a function with one parameter.
I routinely use empty parens for functions that have no parameters in order to make it clear that thing is a function doing something, not some variable only storing a value.
int iResults = 24+45*3/5-23+4*2
There are some folks who can see the order of precedence and apply it perfectly, but most of us cannot. We must use parens.
If you want to always put parenthesis, if there is a function with one parameter, then you can also put them consequently like this (ret in) and this would show equally well that it is a function call. I could use your argument for a call like func (A+B+C) D . How do you know if that is a function call and the parenthesis are not for grouping the arguments? For functions with no parameters I agree with you, that you should always use parenthesis. Otherwise the interpreter would not be able to differentiate between a function ret() and ret(in). But in the end, I guess this discussion is really not very useful. In the end this is probably only dependend on the taste of the programmer, like how variable should be named, curly braces, etc. should be put. Regards, Mathias
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
|
|
Re: Put function help llandale - Mon Feb 07 13:32:03 EST 2011 Mathias Mamsch - Sat Feb 05 17:25:06 EST 2011
If you want to always put parenthesis, if there is a function with one parameter, then you can also put them consequently like this (ret in) and this would show equally well that it is a function call. I could use your argument for a call like func (A+B+C) D . How do you know if that is a function call and the parenthesis are not for grouping the arguments? For functions with no parameters I agree with you, that you should always use parenthesis. Otherwise the interpreter would not be able to differentiate between a function ret() and ret(in). But in the end, I guess this discussion is really not very useful. In the end this is probably only dependend on the taste of the programmer, like how variable should be named, curly braces, etc. should be put. Regards, Mathias
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
I suppose that:
..... string R = A(B C(1)) D
could be either function C with variables A, B, and D, or could be functions A and C with variables B and D.
But I beieve communicating with yourself next month and communicating with the next dude to read your code is VERY important, an opinion that seems to be in the tiny minority, juding from all the dodo code I've seen. Other folks seems to think ..err.. seem to act that either impressing or bewildering the next dude has high priority.
Just wrote this function, the first form is what I wrote and the 2nd is what I could indeed have done.
//******************************
bool IsEntity(Object in_oIrs, int in_Level, char in_cAbrv)
{ // Is the object a well-formed Entity?
// Must be at specified Level with Abreviation that starts with the character,
// and have non-null Heading and Text
// Works for Segments, Elements, Components, and Sub-Components
string Abrv = probeAttr_(in_oIrs, c_NameVerif_Abbrev)
return(level(in_oIrs) == in_Level and
Abrv[0] == in_cAbrv and
!null g_adText and
hasSpecificValue(in_oIrs, g_adText) and
!null g_adText and
hasSpecificValue(in_oIrs, g_adHead)
)
} // end IsEntity()
//******************************
bool IsEntity(Object in_oIrs, int in_Level, char in_cAbrv)
{ // Is the object a well-formed Entity?
string Abrv = probeAttr_(in_oIrs, c_NameVerif_Abbrev); return(level(in_oIrs) == in_Level and Abrv[0] == in_cAbrv and!null g_adText and hasSpecificValue(in_oIrs, g_adText)and!null g_adText and hasSpecificValue(in_oIrs, g_adHead))}
|
|
Re: Put function help Mathias Mamsch - Mon Feb 07 15:20:23 EST 2011 llandale - Mon Feb 07 13:32:03 EST 2011
I suppose that:
..... string R = A(B C(1)) D
could be either function C with variables A, B, and D, or could be functions A and C with variables B and D.
But I beieve communicating with yourself next month and communicating with the next dude to read your code is VERY important, an opinion that seems to be in the tiny minority, juding from all the dodo code I've seen. Other folks seems to think ..err.. seem to act that either impressing or bewildering the next dude has high priority.
Just wrote this function, the first form is what I wrote and the 2nd is what I could indeed have done.
//******************************
bool IsEntity(Object in_oIrs, int in_Level, char in_cAbrv)
{ // Is the object a well-formed Entity?
// Must be at specified Level with Abreviation that starts with the character,
// and have non-null Heading and Text
// Works for Segments, Elements, Components, and Sub-Components
string Abrv = probeAttr_(in_oIrs, c_NameVerif_Abbrev)
return(level(in_oIrs) == in_Level and
Abrv[0] == in_cAbrv and
!null g_adText and
hasSpecificValue(in_oIrs, g_adText) and
!null g_adText and
hasSpecificValue(in_oIrs, g_adHead)
)
} // end IsEntity()
//******************************
bool IsEntity(Object in_oIrs, int in_Level, char in_cAbrv)
{ // Is the object a well-formed Entity?
string Abrv = probeAttr_(in_oIrs, c_NameVerif_Abbrev); return(level(in_oIrs) == in_Level and Abrv[0] == in_cAbrv and!null g_adText and hasSpecificValue(in_oIrs, g_adText)and!null g_adText and hasSpecificValue(in_oIrs, g_adHead))}
For me this is not about making code more obscure, just about avoiding the concatenation mistake that can happen if you embed functions with one parameter. If you want your code to be more understabdable you can do a lot of things, putting in whitespaces and braces just helps to see the structure of the code, not how it works. Looking at your code, why are you checking 'g_adText' for null twice? Could it be that you wanted to check g_adHead for !null? And if g_adText and g_adHead is what I think (constants defined for "Object Heading" and "Object Text", why would you check them for null? So they are probably not constants but some globals that are set in some other function. Because constants are named with a "c_" at the beginning like "c_NameVerif_Abbrev". But on the other side hasSpecific value does need an attribute name and ... wait! Checking on the DXL help these are attribute definitions that are expected. So where are these set? These are the questions I am asking when I first read that code. And then slowly I get to the point of what the programmer was thinking. So understanding your code is only to a very small part about making code structure clear and where you set your braces! Regards, Mathias
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
|
|
Re: Put function help llandale - Mon Feb 07 20:53:33 EST 2011 Mathias Mamsch - Mon Feb 07 15:20:23 EST 2011
For me this is not about making code more obscure, just about avoiding the concatenation mistake that can happen if you embed functions with one parameter. If you want your code to be more understabdable you can do a lot of things, putting in whitespaces and braces just helps to see the structure of the code, not how it works. Looking at your code, why are you checking 'g_adText' for null twice? Could it be that you wanted to check g_adHead for !null? And if g_adText and g_adHead is what I think (constants defined for "Object Heading" and "Object Text", why would you check them for null? So they are probably not constants but some globals that are set in some other function. Because constants are named with a "c_" at the beginning like "c_NameVerif_Abbrev". But on the other side hasSpecific value does need an attribute name and ... wait! Checking on the DXL help these are attribute definitions that are expected. So where are these set? These are the questions I am asking when I first read that code. And then slowly I get to the point of what the programmer was thinking. So understanding your code is only to a very small part about making code structure clear and where you set your braces! Regards, Mathias
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
Well, you found the bug and I was deploying that code just as I read it, so I fixed it and moved on. No matter, that value cannot be null for these module's I'm working.
Not shown was "AttrDef g_adText = find(g_mOriginal, "Object Text"). My standards are "g_" global variable. "ad" means variable of type AttrDef.
While my code is certainly not up to DoD Critical standards, it seems to be in the 99%ile of DXL code that I've seen. Not sure if every line of code should have a long comment explaining it in detail, but indeed I've seen code that does that. In this case perhaps a comment line about what is going on would be appropriate.
Thanks
|
|